package com.imooc.sell.service.impl;

import com.imooc.sell.dao.DayStatDao;
import com.imooc.sell.dao.MonthStatDao;
import com.imooc.sell.dao.SeasonStatDao;
import com.imooc.sell.dataobject.AbstractStat;
import com.imooc.sell.dataobject.SellByDay;
import com.imooc.sell.dataobject.SellByMonth;
import com.imooc.sell.dataobject.SellBySeason;
import com.imooc.sell.dto.StatRateDTO;
import com.imooc.sell.service.StatService;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * 统计业务实现类
 */
@Service
@Slf4j
public class StatServiceImpl implements StatService {

    /**
     * 操作日统计表的dao
     */
    @Autowired
    DayStatDao dayStatDao;
    /**
     * 操作月统计表的dao
     */
    @Autowired
    MonthStatDao monthStatDao;
    /**
     * 操作季度统计表的dao
     */
    @Autowired
    SeasonStatDao seasonStatDao;

    /**
     * 用于转换百分比
     */
    private final static BigDecimal hundredBD = new BigDecimal(100);

    /**
     * 进行统计
     */
    @Override
    public void stat() {
        SellByDay yesData = dayStat();
        monthStat(yesData);
        seasonStat(yesData);
    }

    /**
     * 统计昨日数据
     */
    private SellByDay dayStat() {
        SellByDay yesData = null;
        try {
            /*获取日统计数据*/
            yesData = new SellByDay(dayStatDao.countYesSuccess(),
                    dayStatDao.countYesSuccessSale(),
                    dayStatDao.countYesCancel(),
                    dayStatDao.countYesPayback());
            dayStatDao.save(yesData);
        } catch (Exception e) {
            log.error("{}日统计失败" + getClass());
        }
        return yesData;
    }

    /**
     * 统计月数据
     */
    private void monthStat(SellByDay yesData) {
        SellByMonth monthData = null;
        try {
            monthData = monthStatDao.findLatestMonthData();

            /*判断昨日是否为当月第一天y:插入新纪录n:更新最近一条记录*/
            if (!isMonthFstDay()) {
                monthData.setSellSuccessMonth(monthData.getSellSuccessMonth() + yesData.getSellSuccessYes());
                monthData.setSuccessMonthSale(monthData.getSuccessMonthSale().add(yesData.getSuccessYesSale()));
                monthData.setSellCancelMonth(monthData.getSellCancelMonth() + yesData.getSellCancelYes());
                monthData.setSellPaybackMonth(monthData.getSellPaybackMonth() + yesData.getSellPaybackYes());
                monthStatDao.save(monthData);
            } else {
                /* 插入新纪录*/
                SellByMonth sellByMonth = new SellByMonth(monthData.getSellSuccessMonth() + yesData.getSellSuccessYes(),
                        monthData.getSuccessMonthSale().add(yesData.getSuccessYesSale()),
                        monthData.getSellCancelMonth() + yesData.getSellCancelYes(),
                        monthData.getSellPaybackMonth() + yesData.getSellPaybackYes());
                monthStatDao.save(sellByMonth);
            }

        } catch (Exception e) {
            /* 没有统计记录的时候默认作插入处理*/
            if (null == monthData) {
                monthData = new SellByMonth(yesData.getSellSuccessYes(),
                        yesData.getSuccessYesSale(),
                        yesData.getSellCancelYes(),
                        yesData.getSellPaybackYes());
                monthStatDao.save(monthData);
            } else {
                log.error("{}月统计失败" + getClass());
            }
        }
    }


    /**
     * 判断昨日是否为当月第一天
     */
    private boolean isMonthFstDay() {
        Calendar calendar = Calendar.getInstance();
        return ((calendar.get(Calendar.DAY_OF_MONTH) - 1) == 1);
    }

    /**
     * 统计季度数据
     */
    private void seasonStat(SellByDay yesData) {
        /*日统计如果失败则不进行季度统计*/
        if (null != yesData) {
            Calendar calendar = Calendar.getInstance();
            List<Integer> monthList = Arrays.asList(1, 4, 7, 10);
            SellBySeason seasonData = null;
            try {
                seasonData = seasonStatDao.findLatestSeasonData();
                /* 昨日是否为当月首日*/
                if (1 == (calendar.get(Calendar.DAY_OF_MONTH) - 1)) {
                    /* 昨日所在月是否为季度首月*/
                    if (monthList.contains(calendar.get(Calendar.MONTH))) {
                        /*插入记录 */
                        SellBySeason newData = new SellBySeason(seasonData.getSellSuccessSeason() + yesData.getSellSuccessYes(),
                                seasonData.getSuccessSeasonSale().add(yesData.getSuccessYesSale()),
                                seasonData.getSellCancelSeason() + yesData.getSellCancelYes(),
                                seasonData.getSellPaybackSeason() + yesData.getSellPaybackYes());
                        seasonStatDao.save(newData);
                    }
                }
                /*默认作更新操作 */

                /*设置最新数据*/
                seasonData.setSellSuccessSeason(seasonData.getSellSuccessSeason() + yesData.getSellSuccessYes());
                seasonData.setSuccessSeasonSale(seasonData.getSuccessSeasonSale().add(yesData.getSuccessYesSale()));
                seasonData.setSellCancelSeason(seasonData.getSellCancelSeason() + yesData.getSellCancelYes());
                seasonData.setSellPaybackSeason(seasonData.getSellPaybackSeason() + yesData.getSellPaybackYes());
                seasonStatDao.save(seasonData);
            } catch (Exception e) {
                /* 如果本身没有统计记录则做插入处理*/
                if (seasonData == null) {
                    seasonData = new SellBySeason(yesData.getSellSuccessYes(),
                            yesData.getSuccessYesSale(),
                            yesData.getSellCancelYes(),
                            yesData.getSellPaybackYes());
                    seasonStatDao.save(seasonData);
                } else {
                    log.error("{}季度统计失败" + getClass());
                }
            }
        } else {
            log.error("{}月统计失败" + getClass());
        }
    }

    /**
     * 根据选择方式查询统计数据并分页返回
     */
    public Page<?> findList(int type, Pageable pageable, Date dateStart, Date dateEnd) {
        Page<?> page = null;
        try {
            switch (type) {
                /* 代表按天查询*/
                case 0:
                    page = dayStatDao.findByUpdateTimeBetween(dateStart, dateEnd, pageable);
                    break;
                /* 代表按月查询*/
                case 1:
                    page = monthStatDao.findByUpdateTimeBetween(dateStart, dateEnd, pageable);
                    break;
                /* 代表按季度查询*/
                case 2:
                    page = seasonStatDao.findByUpdateTimeBetween(dateStart, dateEnd, pageable);
                    break;
            }
        } catch (Exception e) {
            log.error("{}统计数据查询失败", getClass());
        }
        return page;
    }

    /**
     * 根据统计数据计算增长率
     */
    @Override
    public StatRateDTO statChangeRate() {
        /* 变化率有意义的条件是至少统计表中有两条非空记录*/

        /* 声明一个返回对象*/
        StatRateDTO dto = new StatRateDTO();
        /* 日销售量变化率*/
        BigDecimal sellSuccessYesRate;
        /* 日销售额变化率*/
        BigDecimal successYesSaleRate;
        /* 日取消量变化率*/
        BigDecimal sellCancelYesRate;
        /* 日退款量变化率*/
        BigDecimal sellPaybackYesRate;
        /* 月销售量变化率*/
        BigDecimal sellSuccessMonthRate;
        /* 月销售额变化率*/
        BigDecimal successMonthSaleRate;
        /* 月取消量变化率*/
        BigDecimal sellCancelMonthRate;
        /* 月退款量变化率*/
        BigDecimal sellPaybackMonthRate;
        /* 季度销售量变化率*/
        BigDecimal sellSuccessSeasonRate;
        /* 季度销售额变化率*/
        BigDecimal successSeasonSaleRate;
        /* 季度取消量变化率*/
        BigDecimal sellCancelSeasonRate;
        /* 季度退款量变化率*/
        BigDecimal sellPaybackSeasonRate;
        /* 用于接受结果的容器*/
        List<SellByDay> dd = null;
        List<SellByMonth> md = null;
        List<SellBySeason> sd = null;
        try {
            /* 获取最近的两条日统计记录*/
            dd = dayStatDao.findLatest2Records();
        } catch (Exception e) {
            log.error("{}系统查询出错", getClass());
        }
        /* 判断是否满足计算变化率的条件*/
        if (null != dd && checked(dd)) {
            sellSuccessYesRate = calc(dd.get(0).getSellSuccessYes(), dd.get(1).getSellSuccessYes());
            successYesSaleRate = calc(dd.get(0).getSuccessYesSale(), dd.get(1).getSuccessYesSale());
            sellCancelYesRate = calc(dd.get(0).getSellCancelYes(), dd.get(1).getSellCancelYes());
            sellPaybackMonthRate = calc(dd.get(0).getSellPaybackYes(), dd.get(1).getSellPaybackYes());
            dto.setSellSuccessYesRate(sellSuccessYesRate);
            dto.setSuccessYesSaleRate(successYesSaleRate);
            dto.setSellCancelYesRate(sellCancelYesRate);
            dto.setSellPaybackYesRate(sellPaybackMonthRate);
        }
        try {
            /* 获取最近的两条日统计记录*/
            md = monthStatDao.findLatest2Records();
        } catch (Exception e) {
            log.error("{}系统查询出错", getClass());
        }
        /* 判断是否满足计算变化率的条件*/
        if (null != md && checked(md)) {
            sellSuccessMonthRate = calc(md.get(0).getSellSuccessMonth(), md.get(1).getSellSuccessMonth());
            successMonthSaleRate = calc(md.get(0).getSuccessMonthSale(), md.get(1).getSuccessMonthSale());
            sellCancelMonthRate = calc(md.get(0).getSellCancelMonth(), md.get(1).getSellCancelMonth());
            sellPaybackYesRate = calc(md.get(0).getSellPaybackMonth(), md.get(1).getSellPaybackMonth());
            dto.setSellSuccessMonthRate(sellSuccessMonthRate);
            dto.setSuccessMonthSaleRate(successMonthSaleRate);
            dto.setSellCancelMonthRate(sellCancelMonthRate);
            dto.setSellPaybackYesRate(sellPaybackYesRate);
        }

        try {
            /* 获取最近的两条季度统计记录*/
            sd = seasonStatDao.findLatest2Records();
        } catch (Exception e) {
            log.error("{}系统查询出错", getClass());
        }
        /* 判断是否满足计算变化率的条件*/
        if (null != sd && checked(sd)) {
            sellSuccessSeasonRate = calc(sd.get(0).getSellSuccessSeason(), sd.get(1).getSellSuccessSeason());
            successSeasonSaleRate = calc(sd.get(0).getSuccessSeasonSale(), sd.get(1).getSuccessSeasonSale());
            sellCancelSeasonRate = calc(sd.get(0).getSellCancelSeason(), sd.get(1).getSellCancelSeason());
            sellPaybackSeasonRate = calc(sd.get(0).getSellPaybackSeason(), sd.get(1).getSellPaybackSeason());
            dto.setSellSuccessSeasonRate(sellSuccessSeasonRate);
            dto.setSuccessSeasonSaleRate(successSeasonSaleRate);
            dto.setSellCancelSeasonRate(sellCancelSeasonRate);
            dto.setSellPaybackSeasonRate(sellPaybackSeasonRate);
        }
        return dto;
    }

    public List<?> findAll(int type) {
        List<?> list = null;
        switch (type) {
            /* 代表按天查询*/
            case 0:
                list = dayStatDao.findAll();
                break;
            /* 代表按月查询*/
            case 1:
                list = monthStatDao.findAll();
                break;
            /* 代表按季度查询*/
            case 2:
                list = seasonStatDao.findAll();
                break;
        }
        return list;
    }

    /**
     * 计算变化率  有问题!!!
     */
    private BigDecimal calc(Number n1, Number n2) {
        BigDecimal d1 = new BigDecimal(n1.doubleValue());
        BigDecimal d2 = new BigDecimal(n2.doubleValue());
        System.out.println(n1);
        System.out.println(n2);
        /* 保留两位小数并且4舍5入*/
        BigDecimal result = new BigDecimal(0);
        try {
            result = d1.subtract(d2).divide(d2, 3, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("{}计算错误", getClass());
        }
        return result.multiply(hundredBD);
    }

    @Test
    public void caltest() {
        BigDecimal b1 = new BigDecimal(5);
        BigDecimal b2 = new BigDecimal(6);
    }

    /**
     * 检查结果是否有两条记录
     */
    private boolean checked(List<? extends AbstractStat> dd) {
        return 2 == dd.size();
    }


}
